/*
    当项目庞大起来，很多时候哪怕两个组件不是父子组件或者没有什么直接关系，也会共用某些数据状态，所以vuex就诞生了。
    要注意的是，如果项目很小，需要共享的状态也比较少，那么用vuex反而会让项目变得臃肿起来。

    vuex的作用：
        1. 页面有多个需要共享的状态，引入vuex，便于维护(非父子通信)
        2. 缓存部分异步数据,减少后端服务的访问，增加用户体验

    安装方式：yarn add vuex@next --save 或者 npm install vuex@next --save即可在项目中添加vuex
*/ 
import { createStore } from "vuex";

import axios from "axios";

const store = createStore({
    /*
        state、mutations、actions、getters之间的关系其实很简单
        state就像data一样，里面用来定义数据，而mutations里可以写很多函数，里面可以修改这些数据，但是只能同步修改，不能异步
        所以尤雨溪搞了个actions，actions里面也可以写函数，这些函数可以调用到mutations里面的函数，actions里面是支持异步任务的
        所以你可以在actions里写异步函数，里面可以请求接口拿到数据，再调用mutations里面的函数去给state里面的数据赋值

        也许你会问了：你说的挺好，怎么个调用法啊？state、mutations、actions他们三个是同一个对象里的不同属性，哪那么容易就能互相调用啊？
        你别急，很简单，每一个mutations里定义的函数，都会收到两个参数，第一个参数就是state，第二个参数是未来别人调用他的时候传的参数。
        那么actions里面的函数又是怎么调用mutations里面的函数的呢，很简单，actions里面的方法会有一个参数叫做store，通过store.commit('xxx')
        即可调用mutations里面的方法，xxx就是mutations里面的方法的名称

        到这里你应该大概清楚流程了吧，actions -> mutations -> state这样一个过程。
        我们在vue组件中，可以通过this.$store.dispatch()方法调用到actions里面的方法，从而实现对于state中数据的更新。
        其实this.$store中也有commit('xxx')方法，你也可以直接调用mutations里面的方法，甚至，你可以通过this.$store.state.xxx直接拿到state中的数据，甚至你还能修改。
        但是原则上来说，我们更建议你走流程，不要直接this.$store.state.xxx = ...;这样去修改

        而getters是做什么的呢？其实他就像vue组件中的computed一样，很多时候我们需要对state中定义的数据稍作处理再拿出来，getters就扮演了这样一个角色。getters里面的方法也都会有一个state作为参数

        相信你看到this.$store一定想到了这是VOA写法下的用法，如果我使用的是VCA呢？很简单，从vuex中引入useStore方法，然后
        const store = useStore();即可，后面怎么做就不用我教了吧

        总结：actions -> mutations -> state这层关系内，vue组件通过dispatch方法调用actions中的方法、actions和vue组件都是通过commit方法调用mutations中的方法，而mutations的方法可以真正的实现对state中数据的更新。从而形成一个产业链
    */ 
    // state就像voa组件中的data一样，定义一些状态，写成函数式，然后放在一个对象里return
    state(){
        return {
            isShowTabbar:true,
            cinemaList:[]
        }
    },
    // 唯一修改状态的位置，同步
    mutations:{
        changeTabbar(state,isShowTabbar){
            state.isShowTabbar = isShowTabbar;
        },
        changeCinemaList(state,list){
            state.cinemaList = list;
        }
    },
    // 同步+异步
    actions:{
        // actions里面的函数都会有一个参数store，其实和vue组件里的store是一个东西，通过store.commit()即可调用mutations里面的函数，把名字传进去即可
        async getCinemaList(store){
            // 需要注意的是，我们这里截止2023.08.23，这样去请求卖座网站的地址都是没问题的。也许等你看到这段代码的时候，人家已经维护了或者修改了地址、请求头要求啥的，也不用疑惑。改成可用的地址或者你自己写个简单的服务端测试也可以的。我这里把测试数据放到src下的data文件夹下的cinemas.js里面。
            let res = await axios({
                method:'get',
                url:'https://m.maizuo.com/gateway?cityId=440300&ticketFlag=1&k=1866886',
                headers:{
                    'X-Client-Info':'{"a":"3000","ch":"1002","v":"5.2.1","e":"16926962702329006145798145"}',
                    'X-Host':'mall.film-ticket.cinema.list'
                }
            });
            // 调用store.commit()，实现调用mutations里面的方法，并且将拿到的数据传过去
            store.commit('changeCinemaList',res.data.data.cinemas);
        }
    },
    getters:{
        // 本案例中有一个根据select选择框中eTicketFlag值的变化，让state.cinemaList随之筛选的需求。但是问题来了，筛选在这里倒是好做，调用个filter就行，但是我要怎么在这里去获取vue组件中eTicketFlag的值呢？其实很简单，我们可以利用函数科里化，或者说是闭包
        filterCinemaList(state){
            return (eTicketFlag)=>{
                return state.cinemaList.filter(cinema=>cinema.eTicketFlag==eTicketFlag);
            }
        }
    }
});

export default store;